package com.shopping.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.nimbusds.jose.JOSEException;
import com.shopping.common.RedisKeySetting;
import com.shopping.common.ResultCode;
import com.shopping.common.ResultValue;
import com.shopping.config.CacheComponent;
import com.shopping.dto.SaveUserVo;
import com.shopping.entity.User;
import com.shopping.mapper.UserMapper;
import com.shopping.util.CommonUtils;
import com.shopping.util.ResponseData;
import com.shopping.util.TokenUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author 张衍斌
 * @version 1.0
 * @program dada-shopping
 * @description 用户服务层
 * @create 2019-08-05 14:36
 */
@Service
public class UserService extends ServiceImpl<UserMapper, User> {

    @Autowired
    private CacheComponent cacheComponent;


    /**
     * @MethodName: login
     * @Description: 登录接口
     * @Param: type
     * @Param: account
     * @Param: password
     * @return: String
     * @Author: 张衍斌
     * @Date: 2019/8/6
     */

    public String login(String type, String account, String password) {
        try {
            //手机获取验证码登录
            if (StringUtils.equals(ResultValue.VERIFICATION_CODE_LOGIN, type)) {
                String key = RedisKeySetting.VALIDATE_CODE + account;
                Object cacheToken = cacheComponent.get(RedisKeySetting.TOKEN_CACHE_KEY + account);
                if (CommonUtils.isNull(cacheToken)) {
                    Object cacheCode = cacheComponent.get(key);
                    if (CommonUtils.isNull(cacheCode)) {
                        //验证码过期
                        return ResponseData.customResult(ResultCode.failure.getCode(), ResultValue.VALIDATE_CODE_EXPIRATION);
                    }
                    if (!StringUtils.equals(cacheCode.toString(), password)) {
                        return ResponseData.customResult(ResultCode.failure.getCode(), ResultValue.VALIDATE_CODE_ERROR);
                    }
                    User user = this.selectOne(new EntityWrapper<User>().eq("phone", account));
                    String token = createToken(user, type);
                    if (user != null) {
                        return ResponseData.resultData(ResultCode.success.getCode(), ResultValue.LOGIN_SUCCESS, token);
                    } else {
                        user.setPhone(account);
                        this.insertOrUpdate(user);
                        return ResponseData.resultData(ResultCode.success.getCode(), ResultValue.LOGIN_SUCCESS, token);
                    }
                } else {
                    Map<String, Object> resultMap = TokenUtil.verificationToken(cacheToken.toString());
                    if (Integer.parseInt(resultMap.get("Result").toString()) == 0) {
                        String mobile = JSON.parseObject(resultMap.get("data").toString()).getString("uid");
                        User user = this.selectOne(new EntityWrapper<User>().eq("phone", mobile));
                        String token = this.createToken(user, ResultValue.ORDINARY_LOGIN);
                        return ResponseData.resultData(ResultCode.success.getCode(), ResultValue.LOGIN_SUCCESS, token);
                    }else {

                    }
                }
                //用户名和密码登录
            } else if (StringUtils.equals(ResultValue.ORDINARY_LOGIN, type)) {
                if (!CommonUtils.isPhone(account)) {
                    return ResponseData.customResult(ResultCode.failure.getCode(), ResultValue.PHONE_FORMAT_ERROR);
                }
                if (CommonUtils.isNull(password)) {
                    return ResponseData.customResult(ResultCode.failure.getCode(), ResultValue.PASSWORD_IS_NOT_BLANK);
                }
                User user = this.selectOne(new EntityWrapper<User>().eq("phone",
                        account).eq("password", password));
                if (null == user) {
                    return ResponseData.customResult(ResultCode.failure.getCode(), ResultValue.USER_NO_EXIST);
                }
                String token = this.createToken(user, type);
                return ResponseData.resultData(ResultCode.success.getCode(), ResultValue.LOGIN_SUCCESS, token);
                //第三方微信登录
            } else if (StringUtils.equals(ResultValue.THIRD_PARTY_WECHAT_LOGIN, type)) {

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResponseData.customResult(ResultCode.failure.getCode(), ResultValue.LOGIN_FAILURE);
    }

    private String createToken(User user, String type) {
        try {
            Map<String, Object> payloadMap = new HashMap<>(20);
            long now = System.currentTimeMillis();
            Long userId = user.getId();
            String phone = user.getPhone();
            if (StringUtils.equals(ResultValue.VERIFICATION_CODE_LOGIN, type)) {
                payloadMap.put("uid", phone);
            } else {
                payloadMap.put("uid", userId);
            }
            payloadMap.put("sta", now);
            payloadMap.put("exp", now + TimeUnit.DAYS.toMillis(1));
            String token = TokenUtil.creatToken(payloadMap);
            if (StringUtils.equals(ResultValue.VERIFICATION_CODE_LOGIN, type)) {
                cacheComponent.set(RedisKeySetting.TOKEN_CACHE_KEY + phone, token, TimeUnit.DAYS.toSeconds(1));
                cacheComponent.set(RedisKeySetting.LOGIN_USER_CACHE_KEY + phone, new Gson().toJson(user), TimeUnit.DAYS.toSeconds(1));
            } else {
                cacheComponent.set(RedisKeySetting.TOKEN_CACHE_KEY + userId, token, TimeUnit.DAYS.toSeconds(1));
                cacheComponent.set(RedisKeySetting.LOGIN_USER_CACHE_KEY + userId, new Gson().toJson(user), TimeUnit.DAYS.toSeconds(1));
            }
            return token;
        } catch (JOSEException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @MethodName: getVerificationCode
     * @Description: 获取验证码接口
     * @Param: account
     * @return: String
     * @Author: 张衍斌
     * @Date: 2019/8/6
     */

    public String register(String mobile, String code) {
        //验证次数key
        String vcnKey = RedisKeySetting.VALIDATE_CODE_NUMBER + mobile;
        //验证码key
        String vcKey = RedisKeySetting.VALIDATE_CODE + mobile;
        Object vcnValue = cacheComponent.get(vcnKey);
        if (CommonUtils.isNotNull(vcnValue)) {
            long number = Long.parseLong(vcnValue.toString());
            if (number > RedisKeySetting.VALIDATE_CODE_NUMBER_VALUE) {
                //获取验证码次数受限
                return ResponseData.customResult(ResultCode.failure.getCode(), ResultValue.VALIDATE_CODE_NUMBER_RESTRICTED);
            }
        }
        String verificationCode = cacheComponent.get(vcKey).toString();
        if (CommonUtils.isNull(verificationCode)) {
            //验证码过期
            return ResponseData.customResult(ResultCode.failure.getCode(), ResultValue.VALIDATE_CODE_EXPIRATION);
        }
        if (!StringUtils.equals(verificationCode, code)) {
            //验证码不正确
            return ResponseData.customResult(ResultCode.failure.getCode(), ResultValue.VALIDATE_CODE_ERROR);
        }
        //设置递增次数
        cacheComponent.incr(vcnKey, 1);
        //设置过期时间
        cacheComponent.expire(vcnKey, CommonUtils.surplusTime());
        return ResponseData.customResult(ResultCode.success.getCode(), ResultValue.REGISTER_SUCCESS);
    }

    /**
     * @MethodName: registerAfter
     * @Description: 注册完之后保存基本信息
     * @Param: userVo
     * @Author: 张衍斌
     * @Date: 2019/8/6
     */

    public String registerAfter(SaveUserVo userVo) {
        if (userVo == null || !CommonUtils.isNumber(userVo.getPhone())) {
            return ResponseData.customResult(ResultCode.failure.getCode(), ResultValue.PHONE_FORMAT_ERROR);
        }
        if (CommonUtils.isNull(userVo.getPassword())) {
            return ResponseData.customResult(ResultCode.failure.getCode(), ResultValue.PASSWORD_IS_NOT_BLANK);
        }
        User user = this.selectOne(new EntityWrapper<User>().eq("phone", userVo.getPhone()));
        user.setPassword(userVo.getPassword());
        user.setNickName(userVo.getNickName());
        user.setUserEmail(userVo.getUserEmail());
        cacheComponent.set(RedisKeySetting.REGISTER_USER_CACHE_KEY + userVo.getPhone(), new Gson().toJson(user), TimeUnit.DAYS.toSeconds(15));
        this.insertOrUpdate(user);
        return ResponseData.customResult(ResultCode.success.getCode(), ResultValue.REGISTER_SUCCESS);
    }

    /**
     * @MethodName: getVerificationCode
     * @Description: 获取验证码
     * @Param: account
     * @return: String
     * @Author: 张衍斌
     * @Date: 2019/8/6
     */

    public String getVerificationCode(String account) {
        String code = CommonUtils.validateCode();
        cacheComponent.set(RedisKeySetting.VALIDATE_CODE + account, code, TimeUnit.SECONDS.toSeconds(20));
        return code;
    }
}
